#include "stm32f10x.h"                  // Device header
#include "Delay.h"                      
#include "OLED.h"                       
#include "PWM.h"                       
#include "Serial.h"                    
#include "MyDMA.h"                      
#include <stdint.h>                    
#include <string.h>                     


uint8_t i = 0;                 // 呼吸灯亮度
uint8_t breath_dir = 0;                 // 呼吸灯方向（0=渐亮，1=渐暗）
uint8_t Line = 1;                  // 名字显示的行
uint32_t time_count = 0;                // 累计时间，用在切换行
uint8_t Line_dir = 1;              // OLED字符飘动方向（1=向下，0=向上）

extern uint8_t PWM_GetFreq(void);  //声明一下函数

// 串口指令:帧头+响应码+当前频率+帧尾（AA 01 频率 BB）。。。
uint8_t uart_ack_buf[4] = {0xAA, 0x02, 0x00, 0xBB}; 

int main(void)
{
   
    OLED_Init();          
    PWM_Init();           
    Serial_Init();        

   
    // 显示名字
    OLED_ShowCN(Line, 6, 0, 1);    
    OLED_ShowCN(Line, 7, 1, 1);    
    OLED_ShowCN(Line, 8, 2, 1);    

	//显示频率
    OLED_ShowString(2, 1, "Freq: ");    
    OLED_ShowNum(2, 6,PWM_GetFreq(), 1); 
    OLED_ShowString(2, 8, "Hz");        

    while(1)
    {
       
		
		
		//LED呼吸功能
        PWM_SetCompare1(i);    
        if (breath_dir == 0)            // 渐亮
        {
            i++;
            if (i >= PWM_GetCurrentARR())
            {
                breath_dir = 1;         // 亮度最大时，变为渐暗
            }
        }
        else                            // 渐暗
        {
            i--;
            if (i <= 0)
            {
                breath_dir = 0;         // 亮度最小时，便为渐亮
            }
        }
        Delay_ms(10);                   
        time_count += 10;               

     
		
		
		
		//名字飘动功能，每呼吸250ms变换一次行
        if (time_count >= 250)          // 累计250ms，名字变一次行
        {
            time_count = 0;             
            OLED_Clear();               

            
            if (Line >= 3)         //到第三行，向上飘动
            {
                Line_dir = 0;
            }
            if (Line <= 1)         // 到第一行，向下飘动
            {
                Line_dir = 1;
            }
			
            // 下面注释的简化版。。。
            Line = (Line_dir == 1) ? (Line + 1) : (Line - 1);
			
//			if (Line_dir == 1) 
//			{
//				Line = Line + 1;  // 方向为1，行数自增
//			} 
//			else 
//			{
//				Line = Line - 1; // 为0自减
//			}

            OLED_ShowCN(Line, 6, 0, 1);
            OLED_ShowCN(Line, 7, 1, 1);
            OLED_ShowCN(Line, 8, 2, 1);
     
            OLED_ShowString(2, 1, "Freq: ");
            OLED_ShowNum(2, 6, PWM_GetFreq(), 1);
            OLED_ShowString(2, 8, "Hz");
        }

		
		
		
		
		
		//修改呼吸灯频率（DMA）代码解释：电脑发送指令，串口UART1接收，存入自身的数据寄存器（USART1->DR），存入一字节后，自动向DMA发送接收请求，并存入DMA的内存缓存
        //当串口停止发送，检测到空闲后出发空闲中断，（计算长度，即不定长），然后CPU读取解析内存缓存，控制呼吸灯频率
        
		//修改呼吸灯频率
        if (Serial_RxFlag == 1)         // 检测到串口指令
        {
            Serial_RxFlag = 0;          // 清除标志

            // 指令合法性校验，用于过滤干扰数据，前面的0xAA和0xBB帧头和帧尾？
            if (Serial_RxBuf[0] == 0xAA && Serial_RxBuf[Serial_RxLen - 1] == 0xBB)
            {
                // 指令码+数据长度校验？
                if (Serial_RxBuf[1] == 0x01 && Serial_RxLen >= 4)
                {
                    //提取频率
                    uint8_t target_freq = Serial_RxBuf[2];
					
                    //使用频率，将频率设为读到的
                    PWM_SetBreathFreq(target_freq);

                    //反馈。
                    uart_ack_buf[2] = PWM_GetFreq();  
                    MyDMA_UART1_Send(uart_ack_buf, 4);       

					//OLED显示
                    OLED_ShowString(2, 6, "  ");             // 清除原频率。用空格
                    OLED_ShowNum(2, 6, PWM_GetFreq(), 1); // 显示新频率

                    
                    i = 0;     // 亮度从最暗开始
                    breath_dir = 0;     // 方向改为渐亮
                }
            }

            // 清空接收缓存。。。
            memset(Serial_RxBuf, 0, SERIAL_RX_BUF_LEN);
        }
    }
}
